import { mergeObjects } from '../utils';
import { RenderEngine } from './render-engine';
import { OffscreenRenderEngine } from './offscreen-render-engine';



export type TimeGridStyles = {
    color: string;
};

export type TimeGridSettings = {
    styles?: Partial<TimeGridStyles>;
};

export const defaultTimeGridStyles: TimeGridStyles = {
    color: 'rgba(90,90,90,0.20)',
};

export class TimeGrid {
    renderEngine: OffscreenRenderEngine | RenderEngine;
    start: number;
    end: number;
    accuracy: number;
    delta: number;
    styles: TimeGridStyles = defaultTimeGridStyles;
    timeUnits = 'ms';
    lastRenderedTime: string = '';  // 添加这个属性来记录上一次渲染的时间
    private _customRenderTimeLineGrid?: (data: any) => void;
    private MIN_PIXEL_DELTA: number;
    constructor(settings: TimeGridSettings,customRenderTimeLineGrid?: (data: any) => void,MIN_PIXEL_DELTA:number=0) {
        this.start = 0;
        this.end = 0;
        this.accuracy = 0;
        this.delta = 0;
        this.setCustomRenderTimeLineGrid(customRenderTimeLineGrid);
        this.MIN_PIXEL_DELTA=MIN_PIXEL_DELTA;
        this.setSettings(settings);
    }

    setDefaultRenderEngine(renderEngine: OffscreenRenderEngine | RenderEngine) {
        this.renderEngine = renderEngine;
        this.timeUnits = this.renderEngine.getTimeUnits();
    }

    setSettings({ styles }: TimeGridSettings) {
        this.styles = mergeObjects(defaultTimeGridStyles, styles);

        if (this.renderEngine) {
            this.timeUnits = this.renderEngine.getTimeUnits();
        }
    }
    // 计算时间轴刻度线的位置和间隔
    recalc() {
        const timeWidth = this.renderEngine.max - this.renderEngine.min;
        // 增加初始线条数量以确保覆盖整个宽度
        const initialLinesCount = Math.ceil(this.renderEngine.width / this.MIN_PIXEL_DELTA) ;
        const initialTimeLineDelta = timeWidth / initialLinesCount;

        const realView = this.renderEngine.getRealView();
        const proportion = realView / (timeWidth || 1);

        this.delta = initialTimeLineDelta / Math.pow(2, Math.floor(Math.log2(1 / proportion)));
        // 修改起始和结束计算逻辑
        this.start = Math.floor((this.renderEngine.positionX - this.renderEngine.min) / this.delta) ;
        this.end = Math.ceil((this.renderEngine.positionX + realView - this.renderEngine.min) / this.delta) ;

        this.accuracy = this.calcNumberFix();
    }

    calcNumberFix() {
        const strTimelineDelta = (this.delta / 2).toString();

        if (strTimelineDelta.includes('e')) {
            return Number(strTimelineDelta.match(/\d+$/)?.[0]);
        }

        const zeros = strTimelineDelta.match(/(0\.0*)/);

        return zeros ? zeros[0].length - 1 : 0;
    }

    getTimelineAccuracy() {
        return this.accuracy;
    }

    forEachTime(cb: (pixelPosition: number, timePosition: number) => void) {
        if (Number.isFinite(this.start) && Number.isFinite(this.end)) {
            for (let i = this.start; i <= this.end; i++) {
                const timePosition = i * this.delta + this.renderEngine.min;
                const pixelPosition = this.renderEngine.timeToPosition(Number(timePosition.toFixed(this.accuracy)));

                cb(pixelPosition, timePosition);
            }
        }
    }
     // 添加 getter 和 setter 方法
    setCustomRenderTimeLineGrid(fn?: (data: any) => void) {
        this._customRenderTimeLineGrid = fn;
    }

    getCustomRenderTimeLineGrid() {
        return this._customRenderTimeLineGrid;
    }
    renderLines(start: number, height: number, renderEngine: OffscreenRenderEngine | RenderEngine = this.renderEngine) {
        renderEngine.setCtxValue('fillStyle', this.styles.color);

        this.forEachTime((pixelPosition: number) => {
            renderEngine.fillRect(pixelPosition, start, 1, height);
        });
    }
    // 渲染时间刻度标签
    renderTimes(renderEngine: OffscreenRenderEngine | RenderEngine = this.renderEngine) {
        renderEngine.setCtxValue('fillStyle', renderEngine.styles.fontColor);
        renderEngine.setCtxFont(renderEngine.styles.font);
        const customRender = this.getCustomRenderTimeLineGrid();
        if(!customRender){
            this.forEachTime((pixelPosition, timePosition) => {
                renderEngine.fillText(
                    timePosition.toFixed(this.accuracy) + this.timeUnits,
                    pixelPosition + renderEngine.blockPaddingLeftRight,
                    renderEngine.charHeight,
                );
            });
        }else{
            let lastRenderedPosition = -Infinity;
            const minRenderDistance = this.MIN_PIXEL_DELTA;
            
            this.forEachTime((pixelPosition, timePosition) => {
                const {currentTime} = customRender(pixelPosition, timePosition);
                if(pixelPosition - lastRenderedPosition >= minRenderDistance){
                    const textX = Math.max(
                        renderEngine.blockPaddingLeftRight,
                        pixelPosition
                    );
                    
                    renderEngine.fillText(
                        currentTime,
                        textX,
                        renderEngine.charHeight,
                    );
                    lastRenderedPosition = textX;
                    this.lastRenderedTime = currentTime;
                }
            }); 
        }
    }
}
